/**
 * Copyright (c) 2016-2023, Michael Yang 杨福海 (fuhai999@gmail.com).
 * <p>
 * Licensed under the GNU Lesser General Public License (LGPL) ,Version 3.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/lgpl-3.0.txt
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.jpress.web.admin;

import com.jfinal.aop.Inject;
import com.jfinal.core.ActionKey;
import com.jfinal.kit.LogKit;
import com.jfinal.kit.Ret;
import com.jfinal.plugin.activerecord.Page;
import io.jboot.db.model.Columns;
import io.jboot.utils.StrUtil;
import io.jboot.web.controller.annotation.RequestMapping;
import io.jpress.JPressConsts;
import io.jpress.commons.flowable.FlowConsts;
import io.jpress.core.flowable.FlowTodoItemVO;
import io.jpress.core.flowable.FlowType;
import io.jpress.core.flowable.FlowableManager;
import io.jpress.core.flowable.FlowableUtil;
import io.jpress.core.menu.annotation.AdminMenu;
import io.jpress.model.FlowDoneItem;
import io.jpress.model.FlowTemplate;
import io.jpress.permission.annotation.NeedPermission;
import io.jpress.permission.annotation.PermissionDef;
import io.jpress.service.DepartmentService;
import io.jpress.service.FlowDoneItemService;
import io.jpress.service.FlowTemplateService;
import io.jpress.service.UserService;
import io.jpress.web.AdminPermissionGroups;
import io.jpress.web.base.AdminControllerBase;
import org.flowable.bpmn.model.*;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;

import javax.validation.constraints.NotBlank;
import java.util.*;

/**
 * @author Michael Yang 杨福海 （fuhai999@gmail.com）
 * @version V1.0
 * @Title: 审核流程管理
 * @Package io.jpress.web.admin
 */

/**
 * @author Michael Yang 杨福海 （fuhai999@gmail.com）
 * @version V1.0
 * @Title: 审核流程管理
 */
@RequestMapping(value = "/admin/flow", viewPath = JPressConsts.DEFAULT_ADMIN_VIEW)
public class _FlowController extends AdminControllerBase {


    @Inject
    private FlowTemplateService templateService;

    @Inject
    private DepartmentService departmentService;

    @Inject
    private UserService userService;

    @Inject
    private FlowDoneItemService flowDoneItemService;


    @PermissionDef(title = "查看我的待办事项", groupId = AdminPermissionGroups.FLOW)
    @AdminMenu(text = "我的待办", groupId = JPressConsts.SYSTEM_MENU_FLOW, order = 0)
    public void todos() {
        TaskService taskService = FlowableUtil.getTaskService();

        // 委派，
//        taskService.delegateTask();

        // 委派后主动获取
//        taskService.resolveTask();

        //转交他人处理
//        taskService.setAssignee

        Long userDepartmentId = userService.findDepartmentId(getLoginedUser().getId());

        TaskQuery taskQuery = taskService.createTaskQuery().or().taskAssignee(getLoginedUser().getId().toString());
        if (userDepartmentId != null) {
            taskQuery.taskCandidateGroup(userDepartmentId.toString());
        }
        taskQuery.endOr();


        long totalCount = taskQuery.count();

        Page<FlowTodoItemVO> page = null;
        if (totalCount <= 0) {
            page = new Page<>(null, getPagePara(), getPageSizePara(), 0, 0);
        } else {
            int firstResult = (getPagePara() - 1) * getPageSizePara();
            int pageSize = getPageSizePara();
            List<Task> datas = taskQuery.orderByTaskCreateTime().desc().listPage(firstResult, pageSize);
            List<FlowTodoItemVO> flowTodoItems = FlowTodoItemVO.formTaskList(datas);

            int totalPage = (int) ((totalCount % pageSize) > 0 ? (totalCount / pageSize + 1) : (totalCount / pageSize));
            page = new Page<>(flowTodoItems, getPagePara(), pageSize, totalPage, (int) totalCount);
        }

        setAttr("page", page);
        render("flow/todos.html");
    }


    /**
     * 查看任务详情
     *
     * @param taskId
     */
    public void todoDetail(String taskId) {

        TaskService taskService = FlowableUtil.getTaskService();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();

        RuntimeService runtimeService = FlowableUtil.getRuntimeService();
        String contentType = (String) runtimeService.getVariable(task.getProcessInstanceId(), FlowConsts.VAR_CONTENT_TYPE);

        setAttr("task", task);

        FlowType flowType = FlowableManager.me().getFlowType(contentType);
        forwardAction(flowType.getDetailAction());
    }



    public void processDetail(String taskId) {
        TaskService taskService = FlowableUtil.getTaskService();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();

        ProcessEngine processEngine = FlowableUtil.getProcessEngine();
        ProcessDefinition processDefinition = processEngine.getRepositoryService().createProcessDefinitionQuery()
                .processDefinitionId(task.getProcessDefinitionId()).singleResult();

        String key = processDefinition.getKey();

        FlowTemplate flowTemplate = templateService.findFirstByProcessKey(key);
        setAttr("flowTemplate", flowTemplate);

        String xmlContent = StrUtil.isNotBlank(flowTemplate.getBpmnXmlContent()) ? flowTemplate.getBpmnXmlContent() : getDefaultXmlContent();
        setAttr("xmlContent", xmlContent.replace('\n', ' '));

        setAttr("taskDefinitionId", task.getTaskDefinitionKey());

        render("flow/flow_view.html");
    }


    public void processDetailByProcessInstanceId(String processInstanceId) {
        TaskService taskService = FlowableUtil.getTaskService();

        Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();

        if (task != null){
            ProcessEngine processEngine = FlowableUtil.getProcessEngine();
            ProcessDefinition processDefinition = processEngine.getRepositoryService().createProcessDefinitionQuery()
                    .processDefinitionId(task.getProcessDefinitionId()).singleResult();

            String key = processDefinition.getKey();

            FlowTemplate flowTemplate = templateService.findFirstByProcessKey(key);
            setAttr("flowTemplate", flowTemplate);

            setAttr("taskDefinitionId", task.getTaskDefinitionKey());

            String xmlContent = StrUtil.isNotBlank(flowTemplate.getBpmnXmlContent()) ? flowTemplate.getBpmnXmlContent() : getDefaultXmlContent();
            setAttr("xmlContent", xmlContent.replace('\n', ' '));
        }

        render("flow/flow_view.html");
    }


    @PermissionDef(title = "查看我的已办事项", groupId = AdminPermissionGroups.FLOW)
    @AdminMenu(text = "我的已办", groupId = JPressConsts.SYSTEM_MENU_FLOW, order = 2)
    public void done() {
        Columns columns = Columns.create("user_id", getLoginedUser().getId());
        Page<FlowDoneItem> page = flowDoneItemService.paginateByColumns(getPagePara(), getPageSizePara(), columns, "id desc");

        setAttr("page", page);
        render("flow/done.html");
    }


    @PermissionDef(title = "查看流程管理", groupId = AdminPermissionGroups.FLOW)
    @AdminMenu(text = "流程管理", groupId = JPressConsts.SYSTEM_MENU_FLOW, order = 5)
    public void template() {
        Columns columns = Columns.create("title", getPara("title"))
                .eq("deployed", getParaToBoolean("deployed"));
        Page<FlowTemplate> templatePage = templateService.paginateByColumns(getPagePara(), getPageSizePara(), columns, "id desc");
        setAttr("page", templatePage);
        render("flow/flow_template.html");
    }


    @PermissionDef(title = "选择流程", groupId = AdminPermissionGroups.FLOW)
    @ActionKey("./template/select")
    public void template_select_layer() {
        Page<FlowTemplate> templatePage = templateService.paginateByColumns(getPagePara(), getPageSizePara(), Columns.EMPTY, "id desc");
        setAttr("page", templatePage);
        render("flow/flow_template_select.html");
    }


    @PermissionDef(title = "编辑/新增审核流程", groupId = AdminPermissionGroups.FLOW)
    @ActionKey("./template/edit")
    public void templateEdit() {
        Long id = getParaToLong();
        if (id != null) {
            setAttr("flowTemplate", templateService.findById(id));
        }
        setAttr("flowTypeMap", FlowableManager.me().getFlowTypeMap());
        render("flow/flow_template_edit.html");
    }


    @NeedPermission("./template/edit")
    public void doSaveTemplate() {
        FlowTemplate flowTemplate = getBean(FlowTemplate.class);
        if (flowTemplate.getId() == null) {
            flowTemplate.setCreatedBy(getLoginedUser().getId());
            flowTemplate.setDeployed(false);
        }
        templateService.saveOrUpdate(flowTemplate);
        renderOkJson();
    }


    @PermissionDef(title = "删除审核流程", groupId = AdminPermissionGroups.FLOW)
    public void doDelTemplate() {
        FlowTemplate flowTemplate = templateService.findById(getIdPara());
        if (flowTemplate == null) {
            renderFailJson("该流程已经被删除");
            return;
        }

        Boolean deployed = flowTemplate.getDeployed();
        if (deployed != null && deployed) {
            renderFailJson("该流程已经发布，无法删除");
            return;
        }

        templateService.deleteById(getIdPara());
        renderOkJson();
    }


    @PermissionDef(title = "发布审核流程", groupId = AdminPermissionGroups.FLOW)
    public void doDeployTemplate() {
        FlowTemplate flowTemplate = templateService.findById(getIdPara());
        if (flowTemplate == null) {
            renderFailJson("该流程已经被删除");
            return;
        }

        Boolean deployed = flowTemplate.getDeployed();
        if (deployed != null && deployed) {
            renderFailJson("该流程已经发布，无法再次发布");
            return;
        }

        if (StrUtil.isBlank(flowTemplate.getBpmnXmlContent()) || StrUtil.isBlank(flowTemplate.getBpmnSvgContent())) {
            renderFailJson("该流程图信息不存在，请先设置配置流程图信息。");
            return;
        }

        RepositoryService repositoryService = FlowableUtil.getRepositoryService();

        try {
            Deployment deployment = repositoryService.createDeployment()
                    .addString("resource.bpmn", flowTemplate.getBpmnXmlContent())
                    .addString("resource.svg", flowTemplate.getBpmnSvgContent())
                    .category(flowTemplate.getDeploymentCategory())
                    .deploy();

            if (deployment.getId() != null) {
                flowTemplate.setDeployed(true);
                flowTemplate.setDeploymentId(deployment.getId());
                flowTemplate.setDeploymentTime(deployment.getDeploymentTime());
                flowTemplate.setDeployedBy(getLoginedUser().getId());
                templateService.update(flowTemplate);
            }
        } catch (Exception e) {
            e.printStackTrace();
            renderFailJson(e.getMessage());
            return;
        }


        renderOkJson();
    }

    @PermissionDef(title = "下线审核流程", groupId = AdminPermissionGroups.FLOW)
    public void doUnDeployTemplate() {
        FlowTemplate flowTemplate = templateService.findById(getIdPara());
        if (flowTemplate == null) {
            renderFailJson("该流程已经被删除");
            return;
        }

        Boolean deployed = flowTemplate.getDeployed();
        if (deployed == null || !deployed) {
            renderFailJson("该流程未发布，无法对齐进行下线");
            return;
        }

        Ret ret = FlowableManager.me().doUnDeployCheck(flowTemplate);
        if (ret.isFail()) {
            renderJson(ret);
            return;
        }


        try {
            RepositoryService repositoryService = FlowableUtil.getRepositoryService();
            repositoryService.deleteDeployment(flowTemplate.getDeploymentId(), true);
        } catch (Exception ex) {
            LogKit.error(ex.toString(), ex);
        }

        flowTemplate.setDeployed(false);
        templateService.update(flowTemplate);

        renderOkJson();
    }


    public void complete(@NotBlank String taskId, @NotBlank String action, String comment) {

        TaskService taskService = FlowableUtil.getTaskService();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();

        if (!hasCompleteTaskPermission(task)) {
            renderFailJson("您没有操作的权限");
            return;
        }


        String currentAssignee = getLoginedUser().getId().toString();
        if (!currentAssignee.equals(task.getAssignee())) {
            taskService.unclaim(taskId);
            //认领任务后，才会在我的待办中显示...
            taskService.claim(taskId, currentAssignee);
        }

        Map<String, Object> variables = new HashMap<>();
        FlowableManager.me().doCompleteProcess(variables, taskId, action, this);

        //如果，builder 为设置其状态，则设置状态为默认的 action
        variables.putIfAbsent(FlowConsts.VAR_ACTION, action);

        //多实例的状态下，设置状态
        setActionCountVariable(taskId, taskService, variables);

        long actionCount = getLongVariable(taskId, taskService, FlowConsts.VAR_ACTION_COUNT);
        variables.put(FlowConsts.VAR_ACTION_COUNT, actionCount + 1);

        if (StrUtil.isNotBlank(comment)) {
            taskService.addComment(taskId, task.getProcessInstanceId(), comment);
        }

        //设置 当前的评论意见
        taskService.setVariable(taskId, FlowConsts.VAR_COMMENT, comment);

        //已办事项
        FlowDoneItem flowDoneItem = new FlowDoneItem();
        flowDoneItem.setUserId(getLoginedUser().getId());
        flowDoneItem.setAction(action);
        flowDoneItem.setComment(comment);
        flowDoneItem.setTaskId(task.getId());
        flowDoneItem.setTaskName(task.getName());
        flowDoneItem.setContentType(taskService.getVariable(taskId, FlowConsts.VAR_CONTENT_TYPE));
        flowDoneItem.setContentId(taskService.getVariable(taskId, FlowConsts.VAR_CONTENT_ID));
        flowDoneItem.setContentTitle(taskService.getVariable(taskId, FlowConsts.VAR_CONTENT_TITLE));
        flowDoneItem.setCreated(new Date());


        //驳回操作
        if (FlowConsts.ACTION_STATUS_REBUT.equals(action)) {
            FlowElement prevFlowElement = FlowableUtil.getPrevFlowElement(task.getProcessDefinitionId(), task.getTaskDefinitionKey());

            //上一个节点是开始节点，则直接取消任务
            if (prevFlowElement instanceof StartEvent) {
                flowDoneItemService.save(flowDoneItem);
                FlowableUtil.stopProcessInstance(task.getProcessInstanceId(), variables);
            }

            //上一个节点是用户节点
            else if (prevFlowElement instanceof UserTask) {
                flowDoneItemService.save(flowDoneItem);
                FlowableUtil.moveActivityTo(task.getProcessInstanceId(), task.getTaskDefinitionKey(), prevFlowElement.getId(), variables);
            }
            //其他节点
            else {
                renderFailJson("上一个任务不是用户任务，无法驳回。");
                return;
            }
        }

        //拒绝操作
        else if (FlowConsts.ACTION_STATUS_REFUSE.equals(action)) {

            Map<String, Object> taskVariables = taskService.getVariables(taskId);

            //总实例数量
            Integer nrOfInstances = (Integer) taskVariables.get("nrOfInstances");

            //会签
            if (nrOfInstances != null && nrOfInstances >= 1) {
                flowDoneItemService.save(flowDoneItem);
                taskService.complete(taskId, variables);
            }
            // 单用户实例（非会签）
            else {
                List<SequenceFlow> outgoingFlows = FlowableUtil.getOutgoingFlows(task.getProcessDefinitionId(), task.getTaskDefinitionKey());

                //判断流出线条是否包含了 拒绝 的线条，如果包含，那么就走包含的，如果没有 拒绝 线条，则直接拒绝文章发布
                boolean hasRefuseOutgoingFlow = false;
                if (outgoingFlows != null) {
                    for (SequenceFlow outgoingFlow : outgoingFlows) {
                        String conditionExpression = outgoingFlow.getConditionExpression();
                        if (StrUtil.isNotBlank(conditionExpression) && "${action==\"refuse\"}".equals(conditionExpression.replace(" ", ""))) {
                            hasRefuseOutgoingFlow = true;
                            break;
                        }
                    }
                }

                //如果存在 "拒绝" 的流向线条，那么则流程往下继续
                if (hasRefuseOutgoingFlow) {
                    flowDoneItemService.save(flowDoneItem);
                    taskService.complete(taskId, variables);
                }

                //如果不存在 "拒绝" 的流向线条，则直接拒绝文章发布。
                else {
                    flowDoneItemService.save(flowDoneItem);
                    FlowableUtil.stopProcessInstance(task.getProcessInstanceId(), variables);
                }
            }
        }

        // 其他操作
        else {
            flowDoneItemService.save(flowDoneItem);
            taskService.complete(taskId, variables);
        }


        renderOkJson();
    }


    /**
     * 判断用户是否有操作 task 的权限
     * 1、分配的用户是当前登录用户：有权限
     * 2、分配的部门是当前用户的部门：有权限
     * 其他：没有权限
     *
     * @param task
     * @return
     */
    private boolean hasCompleteTaskPermission(Task task) {
        if (Objects.equals(task.getAssignee(), getLoginedUser().getId().toString())) {
            return true;
        }

        FlowElement flowElement = FlowableUtil.getFlowElementByDefKey(task.getProcessDefinitionId(), task.getTaskDefinitionKey());
        UserTask userTask = (UserTask) flowElement;

        //candidateGroups 保存的是部门id列表
        List<String> candidateGroups = userTask.getCandidateGroups();
        if (candidateGroups == null || candidateGroups.isEmpty()) {
            return false;
        }

        Long departmentId = userService.findDepartmentId(getLoginedUser().getId());
        if (departmentId == null) {
            return false;
        }

        return candidateGroups.contains(departmentId.toString());
    }

    public void stop(@NotBlank String taskId, @NotBlank String action, String comment) {

        TaskService taskService = FlowableUtil.getTaskService();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();

        if (!hasCompleteTaskPermission(task)) {
            renderFailJson("您没有操作的权限");
            return;
        }


        //已办事项
        FlowDoneItem flowDoneItem = new FlowDoneItem();
        flowDoneItem.setUserId(getLoginedUser().getId());
        flowDoneItem.setAction(action);
        flowDoneItem.setComment(comment);
        flowDoneItem.setTaskId(task.getId());
        flowDoneItem.setTaskName(task.getName());
        flowDoneItem.setContentType(taskService.getVariable(taskId, FlowConsts.VAR_CONTENT_TYPE));
        flowDoneItem.setContentId(taskService.getVariable(taskId, FlowConsts.VAR_CONTENT_ID));
        flowDoneItem.setContentTitle(taskService.getVariable(taskId, FlowConsts.VAR_CONTENT_TITLE));
        flowDoneItem.setCreated(new Date());

        flowDoneItemService.save(flowDoneItem);

        RuntimeService runtimeService = FlowableUtil.getRuntimeService();
        runtimeService.deleteProcessInstance(task.getProcessInstanceId(), comment);

        renderOkJson();

    }


    private void setActionCountVariable(String taskId, TaskService taskService, Map<String, Object> variables) {
        String action = (String) variables.get(FlowConsts.VAR_ACTION);
        if (action == null || StrUtil.isBlank(action)) {
            return;
        }
        Long oldCount;
        switch (action) {
            case FlowConsts.ACTION_STATUS_AGREE:
                oldCount = getLongVariable(taskId, taskService, FlowConsts.VAR_ACTION_AGREE_COUNT);
                variables.put(FlowConsts.VAR_ACTION_AGREE_COUNT, oldCount + 1);
                break;

            case FlowConsts.ACTION_STATUS_REFUSE:
                oldCount = getLongVariable(taskId, taskService, FlowConsts.VAR_ACTION_REFUSE_COUNT);
                variables.put(FlowConsts.VAR_ACTION_REFUSE_COUNT, oldCount + 1);
                break;

            case FlowConsts.ACTION_STATUS_REBUT:
                oldCount = getLongVariable(taskId, taskService, FlowConsts.VAR_ACTION_REBUT_COUNT);
                variables.put(FlowConsts.VAR_ACTION_REBUT_COUNT, oldCount + 1);
                break;

            case FlowConsts.ACTION_STATUS_STOP:
                oldCount = getLongVariable(taskId, taskService, FlowConsts.VAR_ACTION_STOP_COUNT);
                variables.put(FlowConsts.VAR_ACTION_STOP_COUNT, oldCount + 1);
                break;

        }
    }

    private Long getLongVariable(String taskId, TaskService taskService, String variableName) {
        Number oldCount = (Number) taskService.getVariable(taskId, variableName);
        if (oldCount == null) {
            oldCount = 0L;
        }
        return oldCount.longValue();
    }


    @PermissionDef(title = "进行审核流程设计", groupId = AdminPermissionGroups.FLOW)
    @ActionKey("./template/design")
    public void templateDesign() {
        Long id = getParaToLong();
        FlowTemplate flowTemplate = templateService.findById(id);
        setAttr("flowTemplate", flowTemplate);

        String xmlContent = StrUtil.isNotBlank(flowTemplate.getBpmnXmlContent()) ? flowTemplate.getBpmnXmlContent() : getDefaultXmlContent();
        setAttr("xmlContent", xmlContent.replace('\n', ' '));

        FlowType flowType = FlowableManager.me().getFlowType(flowTemplate.getType());
        forwardAction(flowType.getDesignAction());
    }

    private static String getDefaultXmlContent() {
        return defalutXmlContent.replace("{{processId}}", "Process_" + getRandomString());
    }

    // 验证码随机字符数组
    protected static char[] charArray = "1234567890abcdefghjkmnpqrstuvwxyABCDEFGHJKMNPQRSTUVWXY".toCharArray();
    protected static final Random random = new Random(System.nanoTime());
    private static String defalutXmlContent = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
            "<definitions xmlns=\"http://www.omg.org/spec/BPMN/20100524/MODEL\" xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\" xmlns:omgdi=\"http://www.omg.org/spec/DD/20100524/DI\" xmlns:omgdc=\"http://www.omg.org/spec/DD/20100524/DC\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"  targetNamespace=\"http://bpmn.io/bpmn\" exporter=\"bpmn-js (https://demo.bpmn.io)\" exporterVersion=\"8.7.3\"> " +
            "   <process id=\"{{processId}}\" isExecutable=\"true\">    " +
            "       <startEvent id=\"StartEvent\"/>  " +
            "   </process>  " +
            "   <bpmndi:BPMNDiagram id=\"BPMNDiagram_1\">    " +
            "       <bpmndi:BPMNPlane id=\"BPMNPlane_1\" bpmnElement=\"{{processId}}\">      " +
            "           <bpmndi:BPMNShape id=\"_BPMNShape_StartEvent_2\" bpmnElement=\"StartEvent\">        " +
            "               <dc:Bounds height=\"36.0\" width=\"36.0\" x=\"150\" y=\"240.0\"/>      " +
            "           </bpmndi:BPMNShape>    " +
            "       </bpmndi:BPMNPlane>  " +
            "   </bpmndi:BPMNDiagram>" +
            "</definitions>";

    private static String getRandomString() {
        char[] randomChars = new char[6];
        for (int i = 0; i < randomChars.length; i++) {
            randomChars[i] = charArray[random.nextInt(charArray.length)];
        }
        return String.valueOf(randomChars);
    }

    @ActionKey("./template/doSaveBpmnXmlContent")
    @NeedPermission("./template/design")
    public void doSaveBpmnXmlContent() {
        Long id = getParaToLong();

        String processKey = get("processKey");
        if (StrUtil.isBlank(processKey)) {
            renderFailJson("流程 ID 不能为空。");
            return;
        }

        FlowTemplate existModel = templateService.findFirstByColumns(Columns.create("bpmn_process_key", processKey));
        if (existModel != null && !existModel.getId().equals(id)) {
            renderFailJson("不能保存，因为该流程 ID 已经存在。");
            return;
        }


        FlowTemplate flowTemplate = templateService.findById(id);
        if (flowTemplate.getDeployed() != null && flowTemplate.getDeployed()) {
            renderFailJson("不能保存，该流程已经部署完毕。");
            return;
        }


        String xmlContent = getOriginalPara("xmlContent");
        if (StrUtil.isNotBlank(xmlContent)) {
            flowTemplate.setBpmnXmlContent(xmlContent);
        }


        String svgContent = getOriginalPara("svgContent");
        if (StrUtil.isNotBlank(svgContent)) {
            flowTemplate.setBpmnSvgContent(svgContent);
        }


        String deploymentCategory = get("deploymentCategory");
        flowTemplate.setDeploymentCategory(deploymentCategory);

        flowTemplate.setBpmnProcessKey(processKey);
        templateService.update(flowTemplate);
        renderOkJson();
    }


}
